<template>
  <Page auto-content-height>
    <Grid :table-title="tableTitle" v-bind="$attrs">
      <template #toolbar-actions>
        <Button
          class="mr-1"
          @click="createRecord"
          v-if="hasAccessByCodes([`${props.entity.code}:Create`])"
        >
          <template #icon><PlusOutlined /></template>
          {{ $t('daprplus.create') }}
        </Button>
        <div
          v-if="
            hasAccessByCodes([
              `${props.entity.code}:Create`,
              `${props.entity.code}:Update`,
            ])
          "
        >
          <Button class="mr-1" @click="save" type="primary">
            <template #icon><SaveOutlined /></template>
            {{ $t('daprplus.save') }}
          </Button>
          <Button class="mr-1" @click="revert">
            <template #icon><UndoOutlined /></template>
            {{ $t('daprplus.revert') }}
          </Button>
        </div>
        <Button
          class="mr-1"
          @click="deleteRecords"
          v-if="hasAccessByCodes([`${props.entity.code}:Delete`])"
        >
          <template #icon><DeleteOutlined /></template>
          {{ $t('daprplus.delete') }}
        </Button>
        <slot name="extra-tools"></slot>
      </template>
      <template #bool_render="{ row, column }">
        <span
          :style="{
            color: row[column.field] ? '#52c41a' : '#ff4d4f',
            fontSize: '16px',
          }"
        >
          <CheckOutlined v-if="row[column.field]" />
          <CloseOutlined v-else />
        </span>
      </template>
      <template #bool_edit="{ row, column }">
        <Switch
          :checked="row[column.field]"
          :checked-children="$t('daprplus.yes')"
          :un-checked-children="$t('daprplus.no')"
          @change="(checked) => void (row[column.field] = checked)"
        />
      </template>
      <slot></slot>
      <template v-for="(_, name) in $slots" #[name]="slotProps">
        <slot :name="name" v-bind="slotProps"></slot>
      </template>
    </Grid>
  </Page>
</template>

<script
  lang="ts"
  setup
  generic="TInDto extends IInDto, TOutDto extends IOutDto"
>
import type { VbenFormProps } from '#/adapter/form';
import type {
  VxeTableGridOptions,
  VxeGridListeners,
  ExtendedVxeGridApi,
} from '#/adapter/vxe-table';
import { Button, Modal, Switch, message } from 'ant-design-vue';
import {
  PlusOutlined,
  SaveOutlined,
  UndoOutlined,
  DeleteOutlined,
  CheckOutlined,
  CloseOutlined,
} from '@ant-design/icons-vue';
import { Page, type BaseFormComponentType } from '@vben/common-ui';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import type { ApiResult, IInDto, IOutDto, PageQuery } from '#/utils/daprplus';
import { $t } from '#/locales';
import {
  createBaseFormOptions,
  createBaseGridOptions,
  handleApiResult,
} from '#/utils/daprplus';
import { AccessControl, useAccess } from '@vben/access';
import type { EntityInfo } from '#/utils/daprplus';
interface Props<TInDto, TOutDto> {
  tableTitle?: string;
  showSearchForm?: boolean;
  gridOptions: VxeTableGridOptions<TOutDto>;
  formOptions?: VbenFormProps;
  gridEvents?: VxeGridListeners<TOutDto>;
  queryApi?: (query: PageQuery) => Promise<{ items: TOutDto[]; total: number }>;
  createApi?: (records: TInDto[]) => Promise<ApiResult>;
  updateApi?: (records: TInDto[]) => Promise<ApiResult>;
  deleteApi?: (ids: string[]) => Promise<ApiResult>;
  defaultNewRecord?: () => TInDto;
  entity: EntityInfo;
}

const props = withDefaults(defineProps<Props<TInDto, TOutDto>>(), {
  queryApi: undefined,
  createApi: undefined,
  updateApi: undefined,
  deleteApi: undefined,
  defaultNewRecord: () => ({}) as TInDto,
  showSearchForm: false,
  entity: undefined,
});

const emit = defineEmits<{
  (e: 'update:gridApi', value: ExtendedVxeGridApi): void;
}>();

const { hasAccessByCodes } = useAccess();

// 创建基础配置
const baseGridOptions = createBaseGridOptions<TOutDto>(props.queryApi);

// 扩展配置
const finalGridOptions: VxeTableGridOptions<TOutDto> = {
  ...baseGridOptions,
  ...props.gridOptions,
  editConfig: {
    ...{
      ...baseGridOptions.editConfig,
      enabled: hasAccessByCodes([
        `${props.entity.code}:Update`,
        `${props.entity.code}:Update.Update`,
      ]),
    },
  },
};

// 创建基础搜索表单配置
const baseFormOptions = createBaseFormOptions();

// 扩展配置
const finalFormOptions: VbenFormProps<BaseFormComponentType> = {
  ...baseFormOptions,
  ...props.formOptions,
};

const [Grid, gridApi] = useVbenVxeGrid({
  formOptions: props.formOptions ? finalFormOptions : undefined,
  gridOptions: finalGridOptions,
  gridEvents: props.gridEvents,
  showSearchForm: props.showSearchForm,
});

// 向父组件暴露gridApi
emit('update:gridApi', gridApi);

const createRecord = async () => {
  if (!hasAccessByCodes([`${props.entity.code}:Create`])) {
    message.warning(`没有${props.entity.display}的创建权限`);
    return;
  }

  const newRecord = props.defaultNewRecord();
  gridApi.grid.insertAt(newRecord, -1);
  await gridApi.grid.setEditRow(newRecord);
};

const save = async () => {
  const promises: Promise<ApiResult>[] = [];
  const grid = gridApi.grid;
  const error = await grid.validate();
  if (error) {
    message.error(`验证失败：${error}`);
    return;
  }

  const newRecords = hasAccessByCodes([`${props.entity.code}:Create`])
    ? (grid.getInsertRecords() as TInDto[])
    : [];
  const updateRecords = hasAccessByCodes([
    `${props.entity.code}:Update`,
    `${props.entity.code}:Update.Update`,
  ])
    ? (grid.getUpdateRecords() as TInDto[])
    : [];

  if (newRecords.length === 0 && updateRecords.length === 0) {
    message.warning('没有需要保存的数据');
    return;
  }

  if (newRecords.length > 0 && props.createApi) {
    promises.push(props.createApi(newRecords));
  }

  if (updateRecords.length > 0 && props.updateApi) {
    promises.push(props.updateApi(updateRecords));
  }

  const results = await Promise.all(promises);
  // 检查所有操作是否都成功
  var hasError = false;
  for (const result of results) {
    const success = await handleApiResult(result);
    if (!success) {
      hasError = true;
    }
  }

  if (!hasError) {
    await gridApi.query(); // 刷新表格数据
  }
};

const deleteRecords = async () => {
  if (!props.deleteApi) return;
  if (!hasAccessByCodes([`${props.entity.code}:Delete`])) {
    message.warning(`没有${props.entity.display}的删除权限`);
    return;
  }

  const grid = gridApi.grid;
  const selectedRecords = grid.getCheckboxRecords() as TOutDto[];
  if (selectedRecords.length === 0) {
    message.warning('请选择要删除的记录');
    return;
  }

  const ids = selectedRecords.map((record) => record.id!);
  Modal.confirm({
    title: '确认删除',
    content: `确定要删除选中的${selectedRecords.length}条记录吗?`,
    onOk: async () => {
      const result = await props.deleteApi!(ids);
      if (await handleApiResult(result)) {
        await gridApi.query();
      }
    },
  });
};

const revert = async () => {
  const grid = gridApi.grid;
  const newRecords = grid.getInsertRecords();
  if (newRecords.length > 0) {
    await grid.remove(newRecords);
    message.success(`${newRecords.length}条临时数据已清除`);
  }

  const updateRecords = grid.getUpdateRecords();
  if (updateRecords.length > 0) {
    await grid.revertData();
    message.success(`${updateRecords.length}条数据已恢复`);
  }
};
</script>

<style scoped></style>
